#include <windows.h>
#include "HTCGSensor.h"
#include <stdexcept>

// -- Polling the sensor using the SDK dll ------------------------
#define SENSOR_DLL      L"HTCSensorSDK.dll"

HTCGSensor::HTCGSensor(void)
{
	HMODULE hSensorLib = LoadLibrary(SENSOR_DLL);

    if (hSensorLib == NULL)
    {
        printf("Unable to load HTC Sensor DLL");
		throw std::runtime_error("Unable to load HTC Sensor DLL");
    }

    pfnHTCSensorOpen = (PFN_HTCSensorOpen)
        GetProcAddress(hSensorLib, L"HTCSensorOpen");
    pfnHTCSensorClose = (PFN_HTCSensorClose)
        GetProcAddress(hSensorLib, L"HTCSensorClose");
    pfnHTCSensorGetDataOutput = (PFN_HTCSensorGetDataOutput)
        GetProcAddress(hSensorLib, L"HTCSensorGetDataOutput");

    if (pfnHTCSensorOpen == NULL ||
        pfnHTCSensorClose == NULL ||
        pfnHTCSensorGetDataOutput == NULL)
    {
        printf("Unable to find entry point");
		throw std::runtime_error("Unable to find entry point");
    }

	sensorHandle = NULL;
    sensorHandle = pfnHTCSensorOpen(HTC_GSensor);
}

HTCGSensor* HTCGSensor::Create()
{
	HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, L"HTC_GSENSOR_SERVICESTART");
	/*long errorNo = GetLastError();
    if (hEvent == NULL || errorNo != ERROR_ALREADY_EXISTS)
    {
        printf("Unable to create Sensor Event");
		throw;
    }*/
    SetEvent(hEvent);
    CloseHandle(hEvent);
    
    return new HTCGSensor();
}

HTCGSensor::~HTCGSensor(void)
{
	if(sensorHandle != NULL)
	{
		pfnHTCSensorClose(sensorHandle);
		sensorHandle = NULL;
	}

	HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, L"HTC_GSENSOR_SERVICESTOP");
    if (hEvent == NULL || GetLastError() != ERROR_ALREADY_EXISTS)
    {
		printf("Unable to stop Sensor Event");
	    throw std::runtime_error("Unable to stop Sensor Event");
    }

    SetEvent(hEvent);
    CloseHandle(hEvent);
}

//port from http://sensorapi.codeplex.com/
GVector HTCGSensor::GetGVector()
{
	GVector gVector;
	SENSORDATA data;
	pfnHTCSensorGetDataOutput(sensorHandle, &data);

    // HTC's Sensor returns a vector which is around 1000 in length on average..
    // but it really depends on how the device is oriented.
    // When simply face up, my Diamond returns a vector of around 840 in length.
    // While face down, it returns a vector of around 1200 in length.
    // The vector direction is fairly accurate, however, the length is clearly not extremely precise.
    /*
	float htcScaleFactor = 1.0 / 1000.0 * 9.8;
	gVector.x = data.TiltX * htcScaleFactor;
    gVector.y = data.TiltY * htcScaleFactor;
    gVector.z = data.Orientation * htcScaleFactor;
	*/
	gVector.x = data.TiltX ;
    gVector.y = data.TiltY;
    gVector.z = data.Orientation;
	return gVector;
}

void HTCGSensor::Register()
{
	Start(1000);
}

void HTCGSensor::Unregister()
{
	Stop();
}

void HTCGSensor::Process()
{
	GVectorChanged(GetGVector());
}
